package main

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"github.com/astaxie/beego/logs"
	"net"
	"time"
)

func main() {
	//addr := "localhost:7777"
	addr := "192.168.3.38:54321"
	//主动连接服务器
	tcpAddr, err := net.ResolveTCPAddr("tcp4", addr) //TCP连接地址
	if err != nil {
		fmt.Println(err.Error())
		return
	}

	conn, err := net.DialTCP("tcp4", nil, tcpAddr) //建立连接
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	defer conn.Close()
	//声明一个临时缓冲区，用来存储被截断的数据
	var tmpBuffer = make([]byte, 0)
	for {
		//time.Sleep(1 * time.Second)
		//接收服务数据
		buf := make([]byte, 4096) //1024大小的缓冲区
		n, err1 := conn.Read(buf)
		if err1 != nil {
			fmt.Println("err1 = ", err1)
			return
		}
		var fullList [][]byte
		fullList, tmpBuffer = Unpack(append(tmpBuffer, buf[:n]...))
		//var m = make([]map[string]interface{}, 0)
		//err := json.Unmarshal(buf[:n], &m)
		//if err != nil {
		//	fmt.Println(err.Error())
		//	break
		//}
		for _, infos := range fullList {
			var info = make([]map[string]interface{}, 0)
			err := json.Unmarshal(infos[:], &info)
			if err != nil {
				fmt.Println(err.Error())
				continue
			}
			for _, info := range info {
				//logs.Debug(info)
				switch info["type"] {
				case "CMSRLETagLocation":
					location := make([]CMSRLETagLocation, 0)
					err := Parse(info["tags"], &location)
					if err != nil {
						fmt.Println(err.Error())
					}
					for _, v := range location {
						_ = v
						//if v.TagID == "Ul1GuHewor2StOBT" {
						logs.Debug("地图：", v.MapID, "标签：", v.TagID, "X：", v.X, "Y：", v.Y, "Z：", v.Z, "时间：", time.Unix(v.Time, 0).String())
						//}
					}
				case "TagSOS":
					location := make([]TagSOS, 0)
					err := Parse(info["tags"], &location)
					if err != nil {
						fmt.Println(err.Error())
					}
					for _, v := range location {
						logs.Debug(v)
					}
				default:

				}
			}
		}
	}
}

type TagSOS struct {
	TagAddr  string `json:"tag_addr"`
	Location struct {
		MapID int `json:"map_id"`
	} `json:"location"`
	ReportAt time.Time `json:"report_at"`
}

func Parse(body, bean interface{}) error {
	marshal, err := json.Marshal(body)
	if err != nil {
		return err
	}
	return json.Unmarshal(marshal, bean)
}

type CLETag struct {
	Type string        `json:"type"`
	Tags []interface{} `json:"tags"`
}

type CLEAnchor struct {
	Type    string      `json:"type"`
	Anchors interface{} `json:"anchors"`
}

type CLEMap struct {
	Type string      `json:"type"`
	Maps interface{} `json:"maps"`
}

// 标签位置
type CMSRLETagLocation struct {
	TagID string  `json:"tagid"`
	X     float64 `json:"x"`
	Y     float64 `json:"y"`
	Z     float64 `json:"z"`
	MapID int     `json:"mapid"`
	Time  int64   `json:"time"`
}

// 定位统计数据
type CMSRLELocationStatistics struct {
	TagID        string `json:"tagid"`
	BlinkRate    int    `json:"blinkrate"`
	LocationRate int    `json:"locationrate"`
}

// 标签数据
type CMSRLETagData struct {
	TagID        string `json:"tagid"`
	StatusCode   int    `json:"statuscode"`
	Battery      int    `json:"battery"`
	Acceleration []int  `json:"acceleration"`
	Time         int64  `json:"time"`
}

// 基站状态列表
type CMSRLEAnchorList struct {
	AnchorID   string `json:"anchorid"`
	Connection string `json:"connection"`
	IP         string `json:"ip"`
}

// 定位运行状态
type CMSRLERTLSStatus struct {
	MapID  int    `json:"mapid"`
	Status string `json:"status"`
}

const (
	ConstHeader         = "gole"
	ConstHeaderLength   = 4
	ConstSaveDataLength = 4
)

//封包
func Packet(message []byte) []byte {
	return append(append([]byte(ConstHeader), IntToBytes(len(message))...), message...)
}

//解包
func Unpack(buffer []byte) (full [][]byte, cut []byte) {
	length := len(buffer)
	var i int
	for i = 0; i < length; i++ {
		if length < i+ConstHeaderLength+ConstSaveDataLength {
			break
		}
		if string(buffer[i:i+ConstHeaderLength]) == ConstHeader {
			messageLength := BytesToInt(buffer[i+ConstHeaderLength : i+ConstHeaderLength+ConstSaveDataLength])
			if length < i+ConstHeaderLength+ConstSaveDataLength+messageLength {
				break
			}
			data := buffer[i+ConstHeaderLength+ConstSaveDataLength : i+ConstHeaderLength+ConstSaveDataLength+messageLength]
			//readerChannel <- data
			full = append(full, data)
			i += ConstHeaderLength + ConstSaveDataLength + messageLength - 1
		}
	}
	if i == length {
		return full, nil
	}
	return nil, buffer[i:]
}

// IntToBytes 整形转换成字节
func IntToBytes(n int) []byte {
	x := int32(n)

	bytesBuffer := bytes.NewBuffer([]byte{})
	binary.Write(bytesBuffer, binary.BigEndian, x)
	return bytesBuffer.Bytes()
}

// BytesToInt 字节转换成整形
func BytesToInt(b []byte) int {
	bytesBuffer := bytes.NewBuffer(b)

	var x int32
	err := binary.Read(bytesBuffer, binary.BigEndian, &x)
	if err != nil {
		return 0
	}

	return int(x)
}
